package com.hccl.service.parser;

import DM.DialogManager;
import com.hccl.config.Constants;
import com.hccl.exception.updateException;
import entities.StateMachineModel;
import gate.Gate;
import gate.util.GateException;
import org.mongodb.morphia.Datastore;
import org.springframework.stereotype.Component;

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import static com.hccl.config.Constants.*;

/**
 * 实现语义理解Parser类的线程池管理，因为Parser类非线程安全
 */
@Component
public class ParserPool {

    private Constants constants;
    private Datastore datastore;
    private DialogManager dialogManager;                                                      ;
    private BlockingQueue<Parser> pool = new LinkedBlockingQueue<Parser>();

    public ParserPool(Datastore datastore, Constants constants) throws Exception {
        this.datastore = datastore;
        this.constants = constants;
        poolInit();
    }

    /**
     * description: 往线程池中添加Parser对象
     * @Param: null
     * @return null
     */
    public void poolInit() throws Exception {
        dialogManager = dmInit();
        gateInit();
        for (int i = 0; i < constants.getPoolSize(); i++) {
            Parser parser = new Parser(dialogManager, i, datastore);
            this.pool.add(parser);
        }
    }

    /**
     * description: Gate初始化
     * @Param: null
     * @return null
     */
    public void gateInit() throws MalformedURLException, GateException {

        Gate.setGateHome(new File(gateHome).getParentFile());
        Gate.init();
        Gate.getCreoleRegister().registerDirectories(new File(gateANNIEPath).toURI().toURL());
    }

    /**
     * description: 初始化对话管理器
     * @Param: null
     * @return null
     */
    public DialogManager dmInit () throws Exception {
        StateMachineModel smm = null;
        smm = StateMachineModel.getModelFromInternelJson(jsonPath,StateMachineModel.class);
        DialogManager dialogManager = new DialogManager(600, true);// 600s不运行则超时，重置状态机
        dialogManager.setStateMachineModel(smm);
        //dialogManager.setConfig(Boolean.parseBoolean(constants.getUseContext()), constants.getUrl(), constants.getTimeOut());
        dialogManager.setConfig( constants.getUrl(), constants.getTimeOut());
        return dialogManager;
    }

    public Parser take() throws InterruptedException {
        return pool.take();
    }

    public void add(Parser p) throws InterruptedException{
        pool.put(p);
    }

    public void setDialogManager(DialogManager dialogManager){
        this.dialogManager = dialogManager;
    }

    public DialogManager getDialogManager() {
        return dialogManager;
    }

    public BlockingQueue<Parser> getPool() {
        return pool;
    }

    public void setPool(BlockingQueue<Parser> pool) {
        this.pool = pool;
    }

    /**
     * description: 获取更新后的Parser对象列表，大小为阻塞队列的大小
     * @Param: null
     * @return 更新后的Parser列表，用于更新线程池里面的Parser对象
     */
    public List<Parser> getNewParserList() throws updateException {

        try {
            Parser parserTmp = new Parser(dialogManager, 0, datastore);
            parserTmp.parserUpdate();
            dialogManager = dmInit();

            List<Parser> parsersNew = new ArrayList<>();
            for (int i = 0; i < constants.getPoolSize(); i++) {
                Parser parser = new Parser(dialogManager, i, datastore);
                parsersNew.add(parser);
            }
            return parsersNew;
        } catch (Exception e) {
            throw new updateException("更新时getNewParserList()出错。系统尝试自动恢复...");
        }
    }

    /**
     * description: 语料批量测试
     * @Param: null
     * @return null
     */
    public void testCorpus() throws Exception {
        Parser parser = new Parser(0, datastore);
        parser.testCor(parser);
    }


    public Constants getConstants() {
        return constants;
    }

    public void setConstants(Constants constants) {
        this.constants = constants;
    }

    public void updateDialogManager()throws Exception{
        setDialogManager(dmInit());
    }
}
